package eerbaar.action.internal.lib;

import java.util.Map;

import eerbaar.area.IArea;
import eerbaar.context.IContext;
import eerbaar.context.IParams;
import eerbaar.elements.IElement;
import eerbaar.elements.extension.ElementFactory;
import eerbaar.elements.extension.IPoints;
import eerbaar.game.IGame;
import eerbaar.position.IPosition;
import eerbaar.position.PositionFactory;

public class AddElementAction extends AbstractAction {

    private static final String[] paramNames = new String[] { //
    "name", "count", "points", "position", "position2" //
    };

    private int count;
    private String name;
    private String position;
    private String position2;
    private IParams params;
    private int points;

    public AddElementAction(IParams params) {
        super("addElement");
        this.params = params;

        setup(params);
    }

    private void addElement(IContext model, String elementName) {

        IGame game = (IGame) model;
        IArea area = game.getArea();

        for (int i = 0; i < this.count; i++) {

            IPosition p = Global.calcPosition(game, area, this.position);
            if (p == null) {
                break;
            }

            IPosition p2 = Global.calcPosition(game, area, this.position2,
                    false);

            if (p2 != null) {
                line(p, p2, elementName, area);
            } else {
                IElement e = ElementFactory.create(elementName, p);

                IPoints ePoints = e.getExtension(IPoints.class);
                if (ePoints != null) {
                    ePoints.setPoints(this.points);
                }

                area.addElement(e);
            }
        }
    }

    @Override
    public void execute(IContext model) {

        addElement(model, this.name);
    }

    @Override
    public void execute(IContext model, Map<String, String> map) {

        String n = this.name;
        if (this.name.contains("$")) {
            String s = this.name;
            s = s.replace('$', ' ');
            s = s.replace('{', ' ');
            s = s.replace('}', ' ');
            s = s.trim();
            n = map.get(s);
        }

        addElement(model, n);
    }

    @Override
    public String[] getParamNames() {

        return paramNames;
    }

    @Override
    public IParams getParams() {

        return this.params;
    }

    private void line(IPosition p1, IPosition p2, String elementName, IArea area) {

        int x1 = Math.min(p1.getX(), p2.getX());
        int x2 = Math.max(p1.getX(), p2.getX());
        int y1 = Math.min(p1.getY(), p2.getY());
        int y2 = Math.max(p1.getY(), p2.getY());

        for (int x = x1; x <= x2; x++) {
            for (int y = y1; y <= y2; y++) {

                IPosition p = PositionFactory.createPosition(x, y);
                IElement e = ElementFactory.create(elementName, p);

                IPoints ePoints = e.getExtension(IPoints.class);
                if (ePoints != null) {
                    ePoints.setPoints(this.points);
                }

                area.addElement(e);
            }
        }
    }

    @Override
    public void setParams(IParams params) {
        this.params = params;
        setup(params);
    }

    private void setup(IParams params) {

        this.name = params.get("name");
        this.position = params.get("position");
        this.position2 = params.get("position2");
        this.count = Integer.parseInt(params.get("count"));

        if (params.get("points") != null) {
            this.points = Integer.parseInt(params.get("points"));
        }
    }

}
